package com.pucheng.bracelet.viewmodel.home

import android.bluetooth.BluetoothGatt
import androidx.lifecycle.*
import com.blankj.utilcode.util.LogUtils
import com.clj.fastble.callback.BleGattCallback
import com.clj.fastble.callback.BleWriteCallback
import com.clj.fastble.data.BleDevice
import com.clj.fastble.exception.BleException
import com.pucheng.bracelet.app.ble.*
import com.pucheng.bracelet.app.database.repository.AllDataHRRepository
import com.pucheng.bracelet.app.database.repository.DBRepository
import com.pucheng.bracelet.app.database.repository.SleepRepository
import com.pucheng.bracelet.app.util.ByteUtils
import com.pucheng.bracelet.app.util.CacheUtil
import com.pucheng.bracelet.data.bean.*
import kotlinx.coroutines.launch
import me.hgj.jetpackmvvm.base.viewmodel.BaseViewModel
import com.pucheng.bracelet.app.util.DatetimeUtil
import kotlin.concurrent.thread

class HomeViewModel : BaseViewModel() {

    val textDate = MutableLiveData<String>().apply {
        value = DatetimeUtil.getWeekToDay()
    }


    var bleConnectStatus = MutableLiveData<Boolean>().apply {
        value = false
    }
    var batteryStatus = MutableLiveData<Int>().apply {
        value = 0
    }

    var supportFunction = MutableLiveData<Int>().apply {
        value = CacheUtil.getSupportFunction()
    }

    val isOpenHRMeasure = MutableLiveData<Boolean>().apply {
        value = CacheUtil.isOpenHRMeasure()
    }

    val hertRateData = MutableLiveData<HertRateBean>().apply { value = HertRateBean() }
    val sao2Data = MutableLiveData<Sao2Bean>().apply { value = Sao2Bean() }
    val bpInfo =
        MutableLiveData<BloodPressureBean>().apply { value = BloodPressureBean() }

    private val stepsRepository: DBRepository = DBRepository()
    var stepsData = stepsRepository.getStepsInfoToDate(
        DatetimeUtil.formatDate(
            System.currentTimeMillis(),
            DatetimeUtil.DATE_PATTERN
        )
    )
    private val sleepRepository: SleepRepository = SleepRepository()
    var sleepData=MutableLiveData<SleepBean>()
    var sleepDataInfo = sleepRepository.getSleepsInfoToDate(
        DatetimeUtil.formatDate(
            System.currentTimeMillis(),
            DatetimeUtil.DATE_PATTERN
        )
    )
    var sleepTo7Day: LiveData<List<SleepBean>> = sleepRepository.allDataTo7DayToSleep

    private val hrRepository: AllDataHRRepository = AllDataHRRepository()
    var allDayHRData=MutableLiveData<AllHertRateBean>().apply {
        value = AllHertRateBean(DatetimeUtil.formatDate(
            System.currentTimeMillis(),
            DatetimeUtil.DATE_PATTERN_A_H
        ))
    }

    fun connectBle(
        mac: String
//        bleScanAndConnectCallback: BleScanAndConnectCallback?
    ) {
        ClientManager.getInstance().connect(mac, object : BleGattCallback() {
            override fun onStartConnect() {

            }

            override fun onDisConnected(
                isActiveDisConnected: Boolean,
                device: BleDevice?,
                gatt: BluetoothGatt?,
                status: Int
            ) {
                bleConnectStatus.value = false
            }

            override fun onConnectSuccess(
                bleDevice: BleDevice?,
                gatt: BluetoothGatt?,
                status: Int
            ) {
                LogUtils.e("连接成功：${bleDevice!!.name},status=$status")
                bleConnectStatus.value = true
                ClientManager.getInstance().readData(bleDevice,
                    BleUUId.UUID_180F,
                    BleUUId.UUID_2A19, object : MyBleReadCallback() {
                        override fun onReadSuccess(data: ByteArray?) {
                            LogUtils.e("读取内容：${data!![0].toString()}")
                            if (data[0] == 0xff.toByte()) {
                                batteryStatus.value = -1
                            } else {
                                batteryStatus.value = data[0].toInt()
                            }
//                            setLanguage()
                        }
                    })
            }

            override fun onConnectFail(bleDevice: BleDevice?, exception: BleException?) {
                LogUtils.e("连接失败：${bleDevice.toString()},exception=$exception")
                bleConnectStatus.value = false
            }
        })
    }

    /**
     * 设置语言
     */
    fun setLanguage() {
        thread(true) {
            Thread.sleep(3000)
            ClientManager.getInstance().sendCmd(BleUUId.UUID_3802,
                BleUUId.UUID_5A00, BleCmd.SYNC_LANGUAGE, object : BleWriteCallback() {
                    override fun onWriteSuccess(
                        current: Int,
                        total: Int,
                        justWrite: ByteArray?
                    ) {
                        //同步时间
                        syncTime()
                    }

                    override fun onWriteFailure(exception: BleException?) {
                    }
                })
//
//            syncTime()
        }

    }

    /**
     * 设置语言
     */
    private fun syncTime() {
        ClientManager.getInstance().sendCmd(BleUUId.UUID_3802,
            BleUUId.UUID_5A00,
            BleCmd.SYNC_TIME + BleCmd.getSyncTimeCmd(),
            object : BleWriteAndNotifyCallback() {
                override fun onCharacteristicChanged(data: ByteArray?) {

                }

                override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray?) {
                    getStepsNun()
                }

                override fun onWriteFailure(exception: BleException?) {
                }

            })
    }

    fun getStepsNun() {
        ClientManager.getInstance().sendCmd(BleUUId.UUID_3803,
            BleUUId.UUID_6A00, BleCmd.GET_STEPS_INFO, object : BleWriteAndNotifyCallback() {
                override fun onWriteSuccess(
                    current: Int,
                    total: Int,
                    justWrite: ByteArray?
                ) {

                }

                override fun onWriteFailure(exception: BleException?) {
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                    var steps: StepsBean?
                    if (stepsData.value == null) {
                        steps = StepsBean()
                    } else {
                        steps = stepsData.value
                    }
                    steps!!.time =
                        ByteUtils.highLowExchangeToInt(ByteUtils.subBytes(data, 3, 4)).toDouble()
                    steps!!.stepsNum =
                        ByteUtils.highLowExchangeToInt(ByteUtils.subBytes(data, 7, 4)).toString()
                    steps!!.calorie =
                        ByteUtils.highLowExchangeToInt(ByteUtils.subBytes(data, 11, 4))
                    steps!!.distance =
                        ByteUtils.highLowExchangeToInt(ByteUtils.subBytes(data, 15, 4)).toDouble()
                    steps!!.dateTime = DatetimeUtil.formatDate(System.currentTimeMillis(), DatetimeUtil.DATE_PATTERN_A_H)
                    steps!!.date = DatetimeUtil.formatDate(
                        System.currentTimeMillis(),
                        DatetimeUtil.DATE_PATTERN
                    )
                    CacheUtil.setSteps(steps)
                    insertSteps(steps)
//                    stepsData = steps.
                    LogUtils.e(stepsData.value.toString())
                    getSleepDataToBle()
                }
            })
    }

    fun insertSteps(bean: StepsBean) = viewModelScope.launch {
        stepsRepository.insertSteps(bean)
    }

    fun insertSleeps(list: List<SleepBean>) = viewModelScope.launch {
        sleepRepository.insertSleepToList(list)
    }

    fun insertAllHertRate(list: List<AllHertRateBean>) = viewModelScope.launch {
        hrRepository.insertHertrateToList(list)
    }


    /*
     * 获取睡眠数据
     */
    fun getSleepDataToBle() {
        val sleepArray = arrayListOf<Byte>()
        var dataLength = 0
        ClientManager.getInstance().sendCmd(BleUUId.UUID_3803,
            BleUUId.UUID_6A00, BleCmd.GET_SLEEP_DATA, object : BleWriteAndNotifyCallback() {
                override fun onWriteSuccess(
                    current: Int,
                    total: Int,
                    justWrite: ByteArray?
                ) {
                }

                override fun onWriteFailure(exception: BleException?) {
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                    if (data!![0] == ByteUtils.intToByte(0xFB) && data!![1] == ByteUtils.intToByte(
                            0x43
                        ) && data!![2] == ByteUtils.intToByte(0x01)
                    ) {
                        dataLength =
                            ByteUtils.highLowExchangeToInt(ByteUtils.subBytes(data, 3, 4))
                        LogUtils.e("${data!!.size}睡眠数据总长度:${dataLength}")
                        if (dataLength == 0) {
                            getHeartRateMonitor()
                        }
                        sleepArray.clear()
                    } else {
                        sleepArray.addAll(ByteUtils.subBytes(data, 1, data.size - 1).toList())
                        if (sleepArray.size == dataLength) {

                            val infoList: List<SleepBean> =
                                DataUtils.getSleeps(sleepArray.toByteArray())
                            if (!infoList.isNullOrEmpty()) {
                                sleepData.value = infoList.first()
                                insertSleeps(infoList)
                                LogUtils.e("睡眠数据:${sleepData.value.toString()}")
                            }
                            getHeartRateMonitor()
                        }
                    }

                }
            })
    }
    /*
     * 获取睡眠数据
     */
    fun getHeartRateMonitor() {
        val heartRateArray = arrayListOf<Byte>()
        var dataLength = 0
        ClientManager.getInstance().sendCmd(BleUUId.UUID_3803,
            BleUUId.UUID_6A00, BleCmd.GET_HR_DATA_MONITOR, object : BleWriteAndNotifyCallback() {
                override fun onWriteSuccess(
                    current: Int,
                    total: Int,
                    justWrite: ByteArray?
                ) {
                }

                override fun onWriteFailure(exception: BleException?) {
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                    if (data!![0] == ByteUtils.intToByte(0xFB) && data!![1] == ByteUtils.intToByte(
                            0x42
                        ) && data!![2] == ByteUtils.intToByte(0x01)
                    ) {
                        dataLength =
                            ByteUtils.highLowExchangeToInt(ByteUtils.subBytes(data, 3, 4))
                        LogUtils.e("${data!!.size}心率监测数据总长度:${dataLength}")
                        if (dataLength == 0) {
                            getHRData()
                        }
                        heartRateArray.clear()
                    } else {
                        heartRateArray.addAll(ByteUtils.subBytes(data, 1, data.size - 1).toList())
                        if (heartRateArray.size == dataLength) {

                            val infoList: List<AllHertRateBean> =
                                DataUtils.getHeartRateData(heartRateArray.toByteArray())
                            if (!infoList.isNullOrEmpty()) {
                                allDayHRData.value = infoList.first()
                                insertAllHertRate(infoList)
                                LogUtils.e("心率数据:${allDayHRData.value.toString()}")
                            }
                            getHRData()
                        }
                    }

                }
            })
    }

    /**
     * 获取心率数据
     */
    fun getHRData() {
        ClientManager.getInstance().sendCmd(BleUUId.UUID_3803,
            BleUUId.UUID_6A00, BleCmd.GET_HR_DATA, object : BleWriteAndNotifyCallback() {
                override fun onWriteSuccess(
                    current: Int,
                    total: Int,
                    justWrite: ByteArray?
                ) {

                }

                override fun onWriteFailure(exception: BleException?) {
                }

                override fun onCharacteristicChanged(data: ByteArray?) {
                }
            })
    }

}